home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-08-18 | 10.5 KB | 322 lines | [TEXT/R*ch] |
- open
- Obj Fnlib Config Mixture Const Instruct Prim
- Opcodes Prim_opc Buffcode Labels Reloc
- ;
-
- (* 1996.07.13 -- e *)
-
- prim_val lshift_ : int -> int -> int = 2 "shift_left";
- prim_val rshiftsig_ : int -> int -> int = 2 "shift_right_signed";
- prim_val rshiftuns_ : int -> int -> int = 2 "shift_right_unsigned";
-
-
- (* Generation of bytecode for .uo files *)
-
- fun checkAccessIndex n =
- if n <= maxint_byte then () else
- (msgIBlock 0;
- errPrompt "Too many local variables, unable to compile into bytecode";
- msgEOL();
- msgEBlock();
- raise Toplevel)
- ;
-
- fun out_bool_test tst =
- fn PTeq => out tst
- | PTnoteq => out (tst + 1)
- | PTlt => out (tst + 2)
- | PTgt => out (tst + 3)
- | PTle => out (tst + 4)
- | PTge => out (tst + 5)
- | _ => fatalError "out_bool_test"
- ;
-
- fun out_int_const i =
- if i >= minint_short andalso i <= maxint_short then
- if i >= 0 andalso i <= 3
- then
- out (CONST0 + i)
- else
- let val ii1 = i+i+1 in
- if ii1 >= minint_byte andalso ii1 <= maxint_byte then
- (out CONSTBYTE; out (ii1))
- else if ii1 >= minint_short andalso ii1 <= maxint_short then
- (out CONSTSHORT; out_short (ii1))
- else
- (out CONSTINT; out_long i)
- end
- else
- (out CONSTINT; out_long i)
- ;
- fun out_word_const w =
- let prim_val w2i : word -> int = 1 "identity"
- in out_int_const (w2i w) end;
-
- fun out_push_int_const i =
- if i >= minint_short andalso i <= maxint_short then
- if i >= 0 andalso i <= 3
- then
- out (PUSHCONST0 + i)
- else
- let val ii1 = i+i+1 in
- if ii1 >= minint_byte andalso ii1 <= maxint_byte then
- (out PUSH; out CONSTBYTE; out (ii1))
- else if ii1 >= minint_short andalso ii1 <= maxint_short then
- (out PUSH; out CONSTSHORT; out_short (ii1))
- else
- (out PUSHCONSTINT; out_long i)
- end
- else
- (out PUSHCONSTINT; out_long i)
- ;
- fun out_push_word_const w =
- let prim_val w2i : word -> int = 1 "identity"
- in out_push_int_const (w2i w) end;
-
- fun out_tag (CONtag(t,_)) = out t
- | out_tag (EXNtag(name, stamp)) =
- slot_for_tag name stamp
- ;
-
- fun out_header (n, tag) =
- (
- out_tag tag;
- out (lshift_ n 2);
- out (rshiftuns_ n 6);
- out (rshiftuns_ n 14)
- );
-
- fun emit_zam zam =
- case zam of
- Kquote(ATOMsc(INTscon i)) => out_int_const i
- | Kquote(ATOMsc(WORDscon w)) => out_word_const w
- | Kquote(ATOMsc(CHARscon c)) => out_int_const (Char.ord c)
- | Kquote(BLOCKsc(tag, [])) =>
- (case tag of
- CONtag(t,_) =>
- if t < 10 then out (ATOM0 + t) else (out ATOM; out t)
- | EXNtag(name, stamp) =>
- (out ATOM; slot_for_tag name stamp)
- )
- | Kquote sc => (out GETGLOBAL; slot_for_literal sc)
- | Kget_global uid => (out GETGLOBAL; slot_for_get_global uid)
- | Kset_global uid => (out SETGLOBAL; slot_for_set_global uid)
- | Kgetfield n =>
- (if n < 4 then out (GETFIELD0 + n)
- else (out GETFIELD; out_short n)) (* check n? *)
- | Ksetfield n =>
- (if n < 4 then out (SETFIELD0 + n)
- else (out SETFIELD; out_short n)) (* check n? *)
- | Kaccess n =>
- (checkAccessIndex n;
- if n < 8 then out(ACC0 + n) else (out ACCESS; out n))
- | Kenvacc m =>
- let val n = m + 1
- in
- checkAccessIndex n;
- if n < 8 then out(ENV1 + m) else (out ENVACC; out n)
- end
- | Kassign n =>
- (checkAccessIndex n; out ASSIGN; out n)
- | Kapply n =>
- (checkAccessIndex n;
- if n < 5 then out(APPLY1 + n - 1) else (out APPLY; out n))
- | Kappterm (n,z) =>
- (checkAccessIndex n;
- if n < 5 then out(APPTERM1 + n - 1) else (out APPTERM; out n);
- checkAccessIndex z;
- out z)
- | Kpop n => (checkAccessIndex n; out POP; out n)
- | Kgrab n => (checkAccessIndex n; out GRAB; out n)
- | Kreturn n =>
- (checkAccessIndex n;
- if n < 3 then out(RETURN1 + n - 1) else (out RETURN; out n))
- | Kmakeblock(tag,n) =>
- (if n <= 0 then
- fatalError "emit_zam : Kmakeblock"
- else if n < 5 then
- (out (MAKEBLOCK1 + n - 1);
- out_tag tag)
- else
- (out MAKEBLOCK;
- out_header(n, tag)))
- | Klabel lbl =>
- if lbl = Nolabel then fatalError "emit_zam: undefined label"
- else (define_label lbl)
- | Kclosure (lbl,sz) => (out CLOSURE; out sz; out_label lbl)
- | Kclosurerec (lbl,sz) => (out CLOSREC; out (sz - 1); out_label lbl)
- | Kpushtrap lbl => (out PUSHTRAP; out_label lbl)
- | Kpush_retaddr lbl => (out PUSH_RETADDR; out_label lbl)
- | Kbranch lbl => (out BRANCH; out_label lbl)
- | Kbranchif lbl => (out BRANCHIF; out_label lbl)
- | Kbranchifnot lbl => (out BRANCHIFNOT; out_label lbl)
- | Kstrictbranchif lbl => (out BRANCHIF; out_label lbl)
- | Kstrictbranchifnot lbl => (out BRANCHIFNOT; out_label lbl)
- | Kswitch lblvect =>
- let val len = Array.length lblvect
- val () = out SWITCH;
- val () = out len;
- val orig = !out_position
- in
- for (fn i => out_label_with_orig orig (Array.sub(lblvect, i)))
- 0 (len-1)
- end
- | Ktest(tst,lbl) =>
- (case tst of
- Peq_test =>
- (out BRANCHIFEQ; out_label lbl)
- | Pnoteq_test =>
- (out BRANCHIFNEQ; out_label lbl)
- | Pint_test(PTnoteqimm i) =>
- (out PUSH; out_push_int_const i;
- out EQ; out POPBRANCHIFNOT; out_label lbl)
- | Pint_test x =>
- (out_bool_test BRANCHIFEQ x; out_label lbl)
- | Pfloat_test(PTnoteqimm f) =>
- (out PUSH; out PUSH_GETGLOBAL;
- slot_for_literal (ATOMsc(REALscon f));
- out EQFLOAT; out POPBRANCHIFNOT; out_label lbl)
- | Pfloat_test x =>
- (out_bool_test EQFLOAT x; out BRANCHIF; out_label lbl)
- | Pstring_test(PTnoteqimm s) =>
- (out PUSH; out PUSH_GETGLOBAL;
- slot_for_literal (ATOMsc(STRINGscon s));
- out EQSTRING; out POPBRANCHIFNOT; out_label lbl)
- | Pstring_test x =>
- (out_bool_test EQSTRING x; out BRANCHIF; out_label lbl)
- | Pword_test(PTnoteqimm w) =>
- (out PUSH; out_push_word_const w;
- out EQUNSIGN; out POPBRANCHIFNOT; out_label lbl)
- | Pword_test x =>
- (out_bool_test EQUNSIGN x; out BRANCHIF; out_label lbl)
- | Pnoteqtag_test tag =>
- (out BRANCHIFNEQTAG; out_tag tag; out_label lbl)
- )
- | Kbranchinterval(low, high, lbl_low, lbl_high) =>
- (out_push_int_const low;
- if low <> high then out_push_int_const high else out PUSH;
- out BRANCHINTERVAL;
- out_label lbl_low;
- out_label lbl_high
- )
- | Kprim p =>
- (case p of
- Pdummy n =>
- (checkAccessIndex n; out DUMMY; out n)
- | Ptest tst =>
- (case tst of
- Peq_test => out EQ
- | Pnoteq_test => out NEQ
- | Pint_test tst => out_bool_test EQ tst
- | Pfloat_test tst => out_bool_test EQFLOAT tst
- | Pstring_test tst => out_bool_test EQSTRING tst
- | Pword_test tst => out_bool_test EQUNSIGN tst
- | _ => fatalError "emit_zam : Kprim, Ptest")
- | Patom t =>
- if t < 10 then out (ATOM0 + t) else (out ATOM; out t)
- | Pccall(name, arity) =>
- (if arity <= 5 then
- out (C_CALL1 + arity - 1)
- else
- (out C_CALLN; out arity);
- slot_for_c_prim name)
- | Pfloatprim p =>
- out(opcode_for_float_primitive p)
- | Pidentity =>
- ()
- | p =>
- out(opcode_for_primitive p)
- )
- | Kpush => out PUSH
- | Kraise => out RAISE
- | Krestart => out RESTART
- | Kpoptrap => out POPTRAP
- | Kcheck_signals => out CHECK_SIGNALS
- ;
-
- fun emit zams =
- case zams of
- [] => ()
- | Kpush :: Kquote(ATOMsc(INTscon i)) :: C =>
- (out_push_int_const i; emit C)
- | Kpush :: Kquote(ATOMsc(WORDscon w)) :: C =>
- (out_push_word_const w; emit C)
- | Kpush :: Kquote(ATOMsc(CHARscon c)) :: C =>
- (out_push_int_const (Char.ord c); emit C)
- | Kpush :: Kquote(BLOCKsc(tag, [])) :: C =>
- (case tag of
- CONtag(t,_) =>
- if t = 0 then out PUSHATOM0 else (out PUSHATOM; out t)
- | EXNtag(name, stamp) =>
- (out PUSHATOM; slot_for_tag name stamp);
- emit C
- )
- | Kpush :: Kquote sc :: C => (out PUSH_GETGLOBAL; slot_for_literal sc; emit C)
- | Kpush :: Kaccess n :: C =>
- (checkAccessIndex n;
- if n < 8 then out(PUSHACC0 + n) else (out PUSHACC; out n);
- emit C)
- | Kpush :: Kenvacc 0 :: Kapply n :: C =>
- (checkAccessIndex n;
- if n < 5 then
- out(PUSH_ENV1_APPLY1 + n - 1)
- else
- (out PUSHENV1;
- out APPLY; out n);
- emit C)
- | Kpush :: Kenvacc 0 :: Kappterm (n,z) :: C =>
- (checkAccessIndex n;
- if n < 5 then
- (out(PUSH_ENV1_APPTERM1 + n - 1);
- checkAccessIndex z; out z)
- else
- (out PUSHENV1;
- out APPTERM; out n;
- checkAccessIndex z; out z);
- emit C)
- | Kpush :: Kenvacc m :: C =>
- let val n = m + 1
- in
- checkAccessIndex n;
- if n < 8 then out(PUSHENV1 + m) else (out PUSHENVACC; out n);
- emit C
- end
- | Kpush :: Kget_global uid :: Kapply n :: C =>
- (checkAccessIndex n;
- if n < 5 then
- (out(PUSH_GETGLOBAL_APPLY1 + n - 1);
- slot_for_get_global uid)
- else
- (out PUSH_GETGLOBAL;
- slot_for_get_global uid;
- out APPLY; out n);
- emit C)
- | Kpush :: Kget_global uid :: Kappterm (n,z) :: C =>
- (checkAccessIndex n;
- if n < 5 then
- (out(PUSH_GETGLOBAL_APPTERM1 + n - 1);
- checkAccessIndex z; out z;
- slot_for_get_global uid)
- else
- (out PUSH_GETGLOBAL;
- slot_for_get_global uid;
- out APPTERM; out n;
- checkAccessIndex z;
- out z);
- emit C)
- | Kpush :: Kget_global uid :: C =>
- (out PUSH_GETGLOBAL;
- slot_for_get_global uid;
- emit C)
- | Kgetfield 0 :: Kgetfield 0 :: C =>
- (out GETFIELD0_0; emit C)
- | Kgetfield 0 :: Kgetfield 1 :: C =>
- (out GETFIELD0_1; emit C)
- | Kgetfield 1 :: Kgetfield 0 :: C =>
- (out GETFIELD1_0; emit C)
- | Kgetfield 1 :: Kgetfield 1 :: C =>
- (out GETFIELD1_1; emit C)
- | zam :: C =>
- (emit_zam zam; emit C)
- ;
-